package org.abettor.tanqiu.gameloop.object;

import java.util.Iterator;
import java.util.LinkedList;

import org.abettor.tanqiu.gameloop.Constants;


import com.badlogic.gdx.math.Vector2;

/**
 * 弹球的地图
 * 
 * @author jzh
 * 
 */
public class BallMap {
	
	private LinkedList<BallMapPart> mapList = new LinkedList<BallMapPart>();

	/**
	 * 地图的构造函数
	 * 
	 * @param parts
	 */
	public BallMap(BallMapPart... parts) {
		for (BallMapPart part : parts) {
			mapList.add(part);
		}
	}

	/**
	 * 获得地图的第一个部件
	 * 
	 * @return
	 */
	public BallMapPart getFirstMapPart() {
		return mapList.get(0);
	}
	/**
	 * 地图模块的个数
	 * @return
	 */
	public int size(){
		return mapList.size();
	}
	/**
	 * 获得地图
	 * @param index
	 * @return
	 */
	public BallMapPart getBallMapPart(int index){
		return mapList.get(index);
	}
	/**
	 * 获得地图的下一个组件
	 * 
	 * @param part
	 * @return
	 */
	public BallMapPart getNextMap(BallMapPart part) {
		Iterator<BallMapPart> itr = mapList.iterator();
		while (itr.hasNext()) {
			BallMapPart tmp = itr.next();
			if (tmp == part) {
				if (itr.hasNext()) {
					return itr.next();
				} else {
					return null;
				}
			}
		}
		return null;
	}

	/**
	 * 获得地图的上一个组件
	 * 
	 * @param part
	 * @return
	 */
	public BallMapPart getPreMap(BallMapPart part) {
		for (int i = 0; i < mapList.size(); i++) {
			BallMapPart tmp = mapList.get(i);
			if (tmp == part) {
				if (i == 0) {
					return null;
				} else {
					return mapList.get(i - 1);
				}
			}
		}
		return null;
	}

	/**
	 * 获得地图开始的坐标
	 * 
	 * @return
	 */
	public Vector2 startPosition() {
		return mapList.get(0).getBegin();
	}

	/**
	 * 获得地图结束坐标
	 * 
	 * @return
	 */
	public Vector2 endPosition() {
		return mapList.get(mapList.size() - 1).getEnd();
	}

	/**
	 * 获得球沿轨道正向运动时，若干时间后所处的位置
	 * 
	 * @param v
	 * @param deltaTime
	 * @return
	 */
	public Vector2 nextPosition(Vector2 position, float v, float a,
			float deltaTime) {
		float distance = (float)(v * deltaTime/1000 + 0.5*a*deltaTime*deltaTime/1000);
		return nextPosition(position,distance);
	}
	/**
	 * 获得相邻的下一个球的位置
	 * @param position
	 * @return
	 */
	public Vector2 nextNeiborPosition(Vector2 position){
		//获得当前的组件
		int index = getMapPartIndex(position);
		if(index==-1){
			return Constants.END_BALL_POINT;
		}
		BallMapPart currentMapPart = getMapPart(index);
		Vector2 curPos = new Vector2(position);
		float distance = 0;
		for(;;){
			Vector2 tmpVec = currentMapPart.nextStep(curPos, Constants.STEP_LEN);
			if(tmpVec == null){//进行下一个地图模块的差值
				currentMapPart = getMapPart(index + 1);
				if(currentMapPart == null){
					return Constants.END_BALL_POINT;
				}
				tmpVec = currentMapPart.getBegin();
				distance = position.dst(tmpVec);
				if(Math.abs(distance - 2*Constants.BALL_RAIDUS) < Constants.STEP_PRE){
					return tmpVec;
				}else{
					curPos = tmpVec;
				}
			}else{//本地图的差值
				distance = position.dst(tmpVec);
				if(Math.abs(distance - 2*Constants.BALL_RAIDUS) < Constants.STEP_PRE){
					return tmpVec;
				}else{
					curPos = tmpVec;
				}
			}
		}
	}
	/**
	 * 获得球沿轨道运动时，若干时间后所处的位置
	 * 
	 * @param distance
	 * @return
	 */
	public Vector2 nextPosition(Vector2 position, float distance) {
//		if(2>1){
//			Vector2 a1 = new Vector2();
//			a1.x = position.x+0.5222f;
//			a1.y = position.y;
//			return a1;
//		}
		int index = getMapPartIndex(position);
		if(index == -1){
			return Constants.END_BALL_POINT;//对应的位置没有在地图内，暂时先返回终点坐标
		}
		float dis = 0;
		BallMapPart currentMapPart = getMapPart(index);
		Vector2 currentPosition = new Vector2();
		currentPosition.set(position);
		float tmpDis = dis  + getRemainDistance(currentPosition,currentMapPart);
		while(tmpDis < distance){
			currentMapPart = getMapPart(index+1);
			if(currentMapPart==null){
				return Constants.END_BALL_POINT;
			}
			currentPosition.set(currentMapPart.getBegin());
			dis = tmpDis;
			tmpDis =dis +  getRemainDistance(currentPosition,currentMapPart);
		}
		//计算剩下的距离
		float moveInstance = distance - dis;
		return getRemainDistancePosition(currentMapPart,currentPosition,moveInstance);
	}
	private float getRemainDistance(Vector2 position,BallMapPart part){
		if(part instanceof BallMapSquarePart){
			return position.dst(part.getEnd());
		}else{
			float tmpRadius =  Constants.SPHEREPART_RAIDUS - Constants.BALL_RAIDUS;
			float distance = position.dst(part.getEnd());
			float hudu = (float)(Math.asin(distance/(tmpRadius*2)))*2;
			return (float)(hudu * tmpRadius);
		}
	}
	//计算特定距离后所处于的位置
	private Vector2 getRemainDistancePosition(BallMapPart part,Vector2 position,float distance){
		Vector2 retVector2 = new Vector2();
		if(part instanceof BallMapSquarePart){
			BallMapSquarePart squarePart = (BallMapSquarePart) part;
			switch(squarePart.getType()){
			case BallMapSquarePart.TYPE_HORIZONTAL:
				if(part.getEnd().x - part.getBegin().x > 0){
					retVector2.x = position.x + distance;
					retVector2.y = part.getBegin().y;
				}else{
					retVector2.x = position.x - distance;
					retVector2.y = part.getBegin().y;
				}
				break;
			case BallMapSquarePart.TYPE_LEFTSLANT:
			case BallMapSquarePart.TYPE_RIGHTSLANT:
				if(part.getEnd().x - part.getBegin().x > 0){
					retVector2.x = (float)(position.x + distance*Math.sin(Math.PI/4));
					retVector2.y = (float)(position.y + distance*Math.sin(Math.PI/4));
				}else{
					retVector2.x = (float)(position.x - distance*Math.sin(Math.PI/4));
					retVector2.y = (float)(position.y - distance*Math.sin(Math.PI/4));
				}
				break;
			case BallMapSquarePart.TYPE_VERTICAL:
				if(part.getEnd().y - part.getBegin().y > 0){
					retVector2.y = position.y + distance;
					retVector2.x = part.getBegin().x;
				}else{
					retVector2.y = position.y - distance;
					retVector2.x = part.getBegin().x;
				}
				break;
			}
			return retVector2;
		}else{
			BallMapSpherePart spherePart = (BallMapSpherePart) part;
			Vector2 beginPot = spherePart.getBegin();
			Vector2 endPot = spherePart.getEnd();
			Vector2 circlePot = spherePart.getCircleDot();
			float tmpRadius =  Constants.SPHEREPART_RAIDUS - Constants.BALL_RAIDUS;
			float hudu = (float)((distance / tmpRadius));
			float lineDis = (float)(Math.sin(hudu/2)*2*tmpRadius);
			switch(spherePart.getType()){
			case BallMapSpherePart.TYPE_1:
			case BallMapSpherePart.TYPE_2:
				if(endPot.x > beginPot.x){
					float cosv = (float)((position.y - circlePot.y)/tmpRadius);
					cosv = Math.abs(cosv);
					float jiaodu = (float)Math.acos(cosv);
					float jiao = (float)(jiaodu - hudu/2);
					retVector2.y = (float)(position.y + lineDis * Math.sin(jiao));
					retVector2.x = (float)(position.x + lineDis * Math.cos(jiao));
				}else{
					float cosv = (float)((position.y - circlePot.y)/tmpRadius);
					cosv = Math.abs(cosv);
					float jiaodu = (float)Math.acos(cosv);
					float jiao = (float)(jiaodu + hudu/2);
					retVector2.x = (float)(position.x - lineDis * Math.cos(jiao));
					retVector2.y = (float)(position.y - lineDis * Math.sin(jiao));
				}
				break;
			case BallMapSpherePart.TYPE_3:
			case BallMapSpherePart.TYPE_4:
				if(endPot.x > beginPot.x){
					float cosv = (float)((position.y - circlePot.y)/tmpRadius);
					cosv = Math.abs(cosv);
					float jiaodu = (float)Math.acos(cosv);
					float jiao = (float)(jiaodu + hudu/2);
					retVector2.x = (float)(position.x + lineDis * Math.cos(jiao));
					retVector2.y = (float)(position.y - lineDis * Math.sin(jiao));
				}else{
					float cosv = (float)((position.y - circlePot.y)/tmpRadius);
					cosv = Math.abs(cosv);
					float jiaodu = (float)Math.acos(cosv);
					float jiao = (float)(jiaodu - hudu/2);
					retVector2.x = (float)(position.x - lineDis * Math.cos(jiao));
					retVector2.y = (float)(position.y + lineDis * Math.sin(jiao));
				} 
				break;
			case BallMapSpherePart.TYPE_5:
			case BallMapSpherePart.TYPE_6:
				if(endPot.y < beginPot.y){
					float cosv = (float)((position.y - circlePot.y)/tmpRadius);
					cosv = Math.abs(cosv);
					float jiaodu = (float)Math.acos(cosv);
					float jiao = (float)(jiaodu - hudu/2);
					retVector2.x = (float)(position.x - lineDis * Math.cos(jiao));
					retVector2.y = (float)(position.y - lineDis * Math.sin(jiao));
				}else{
					float cosv = (float)((position.y - circlePot.y)/tmpRadius);
					cosv = Math.abs(cosv);
					float jiaodu = (float)Math.acos(cosv);
					float jiao = (float)(jiaodu + hudu/2);
					retVector2.x = (float)(position.x + lineDis * Math.cos(jiao));
					retVector2.y = (float)(position.y + lineDis * Math.sin(jiao));
				}
				break;
			case BallMapSpherePart.TYPE_7:
			case BallMapSpherePart.TYPE_8:
				if(endPot.y > beginPot.y){
					float cosv = (float)((position.y - circlePot.y)/tmpRadius);
					cosv = Math.abs(cosv);
					float jiaodu = (float)Math.acos(cosv);
					float jiao = (float)(jiaodu + hudu/2);
					retVector2.x = (float)(position.x - lineDis * Math.cos(jiao));
					retVector2.y = (float)(position.y + lineDis * Math.sin(jiao));
				}else{
					float cosv = (float)((position.y - circlePot.y)/tmpRadius);
					cosv = Math.abs(cosv);
					float jiaodu = (float)Math.acos(cosv);
					float jiao = (float)(jiaodu - hudu/2);
					retVector2.x = (float)(position.x + lineDis * Math.cos(jiao));
					retVector2.y = (float)(position.y - lineDis * Math.sin(jiao));
				}
				break;
			}
			return retVector2;
		}
	}

	// 获得特定坐标所在的地图块
	private int getMapPartIndex(Vector2 positon) {
		for (int i = 0; i < mapList.size(); i++) {
			BallMapPart part = mapList.get(i);
			Vector2 asixA = part.getBegin();
			Vector2 asixB = part.getEnd();
			if (part instanceof BallMapSquarePart) {// 长方形地图
				BallMapSquarePart tmpPart = (BallMapSquarePart) part;
				Vector2 toComparePoint = new Vector2();
				switch (tmpPart.getType()) {
				case BallMapSquarePart.TYPE_HORIZONTAL:
					toComparePoint.y = tmpPart.getBegin().y;
					toComparePoint.x = positon.x;
					break;
				case BallMapSquarePart.TYPE_LEFTSLANT:
				case BallMapSquarePart.TYPE_RIGHTSLANT:
					toComparePoint.x = (asixA.x - asixA.y + positon.x + positon.y) / 2;// 获得横坐标的公式
					toComparePoint.y = (asixA.y - asixA.x + positon.x + positon.y) / 2;// 获得纵坐标的公式
					break;
				case BallMapSquarePart.TYPE_VERTICAL:
					toComparePoint.x = tmpPart.getBegin().x;
					toComparePoint.y = positon.y;
					break;
				}
				if (positon.dst(toComparePoint) < Constants.SQUAREPART_WIDTH / 2) {
					switch (tmpPart.getType()) {
					case BallMapSquarePart.TYPE_HORIZONTAL:
						if (((positon.x >= asixA.x) ^ (positon.x <= asixB.x)) == false) {
							return i;
						}
						break;
					case BallMapSquarePart.TYPE_LEFTSLANT:
					case BallMapSquarePart.TYPE_RIGHTSLANT:
						if (((positon.x >= asixA.x) ^ (positon.x <= asixB.x)) == false) {
							return i;
						}
						break;
					case BallMapSquarePart.TYPE_VERTICAL:
						if(((positon.y >= asixA.y) ^ (positon.y <= asixB.y))==false){
							return i;
						}
						break;
					}
				}
			} else {// 圆形地图块
				BallMapSpherePart tmpPart = (BallMapSpherePart) part;
				Vector2 dot = tmpPart.getCircleDot();
				//在圆形地图组件的内部
				float tmpRadius =  Constants.SPHEREPART_RAIDUS - Constants.BALL_RAIDUS;
				if(positon.dst(dot) < Constants.SPHEREPART_RAIDUS){
					float dis = asixA.dst(positon)/2;
					float hudu = (float)(2 * Math.asin(dis/tmpRadius));
					if(hudu < Math.PI/4){//扫过的面积小于pi/4,肯定在这个块内
						return i;
					}
				}
			}
		}
		return -1;
	}

	// 获得特定坐标的地图块
	private BallMapPart getMapPart(int index) {
		if(index > mapList.size() - 1){
			return null;
		}
		return this.mapList.get(index);
	}
}
